//
// Created by Akashic on 2024/7/9.
//

#include "linkmap.h"


void freeKeyNode(void *key){
    if (key != NULL){
        KeyNode *keyNode = (KeyNode *)key;

        if (keyNode->key != NULL){
            keyNode->freeKey(keyNode->key);
        }

        if (keyNode->data != NULL){
            free(keyNode->data);
        }
        free(keyNode);
    }
}

LinkMap *createMap(void (*freeKey)(void *key),
                   void  (*freeData)(void *data),
                   bool (*filter)(void *key1, void *key2)) {

    LinkMap *linkMap = (LinkMap *) malloc(sizeof(LinkMap));
    linkMap->keyList = create(&freeKeyNode);
    linkMap->freeKey = freeKey;
    linkMap->freeData = freeData;
    linkMap->filter = filter;
    return linkMap;
}

void insert(LinkMap *linkMap, void *key, void *value) {
    Iterator iter;
    iterator(&iter, linkMap->keyList);
    bool update = false;
    while (hasNext(&iter)) {
        KeyNode *keyNode = next(&iter);
        bool f = linkMap->filter(keyNode->key, key);
        if (f == true) {
            LinkList *list = keyNode->data;
            addFirst(list, value);
            update = true;
            break;
        }
    }
    if (update == false) {
        KeyNode *keyNode = (KeyNode *) malloc(sizeof(KeyNode));
        keyNode->key = key;
        keyNode->freeKey = linkMap->freeKey;

        LinkList *linkList = create(linkMap->freeData);
        addFirst(linkList, value);
        keyNode->data = linkList;
        addFirst(linkMap->keyList, keyNode);
    }
}

LinkList *getList(LinkMap *linkMap, void *key) {
    Iterator iter; iterator(&iter, linkMap->keyList);
    while (hasNext(&iter)) {
        KeyNode *keyNode = next(&iter);
        int f = linkMap->filter(keyNode->key, key);
        if (f == 1) {
            return keyNode->data;
        }
    }
    return NULL;
}

void delKey(LinkMap *linkMap, void *key) {
    Iterator iter; iterator(&iter, linkMap->keyList);
    while (hasNext(&iter)) {
        KeyNode *keyNode = next(&iter);
        int f = linkMap->filter(keyNode->key, key);
        if (f == 1) {
            Iterator iter2; iterator(&iter2, keyNode->data);
            while (hasNext(&iter2)){
                delNode(&iter2);
            }
            delNode(&iter);
            break;
        }
    }
}
